package cc.rengu.oltp.utility.util.sm2;

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;

public class Sm2BasicAgreement {

    protected ECPrivateKeyParameters privKey;

    public void init(CipherParameters parameters) {
        if (parameters instanceof ParametersWithRandom) {
            parameters = ((ParametersWithRandom) parameters).getParameters();
        }
        this.privKey = (ECPrivateKeyParameters) parameters;
    }

    public int getFieldSize() {
        return (privKey.getParameters().getCurve().getFieldSize() + 7) / 8;
    }

    public BigInteger[] calculateAgreement(CipherParameters pubKey) throws Exception {
        ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey;
        if (!pub.getParameters().equals(privKey.getParameters())) {
            throw new Exception("ECDH public key has wrong domain parameters");
        }

        ECPoint P = pub.getQ().multiply(privKey.getD()).normalize();
        if (P.isInfinity()) {
            throw new Exception("Infinity is not a valid agreement value for ECDH");
        }
        return new BigInteger[]{P.getAffineXCoord().toBigInteger(), P.getAffineYCoord().toBigInteger()};
    }
}
